JavaScript的严格模式和正常模式

"use strict";
顾名思义也就是 JavaScript 会在所谓严格模式下执行,其一个主要的优势在于能够强制开发者避免使用未声明的变量。对于老版本的浏览器或者执行引擎则会自动忽略该指令。


在正常模式中,如果一个变量没有声明就赋值,默认是全局变量。严格模式禁止这种用法,全局变量必须显式声明。

"use strict";
  v = 1; // 报错,v未声明
  for(i = 0; i < 2; i++) { // 报错,i未声明
  }

因此,严格模式下,变量都必须先用var命令声明,然后再使用。


Javascript语言的一个特点,就是允许"动态绑定",即某些属性和方法到底属于哪一个对象,不是在编译时确定的,而是在运行时(runtime)确定的。
严格模式对动态绑定做了一些限制。某些情况下,只允许静态绑定。也就是说,属性和方法到底归属哪个对象,在编译阶段就确定。这样做有利于编译效率的提高,也使得代码更容易阅读,更少出现意外。

因为下面的代码不是在严格模式下执行,并且this的值不会在函数执行时被设置,此时的this的值会默认设置为全局对象。

function f2(){
  "use strict"; // 这里是严格模式
  return this;
}

f2() === undefined; // true

更全面的信息参考这个链接


JavaScript作用域和变量提升

考虑下面程序的运行结果

var foo = 1;  
function bar() {  
    if (!foo) {  
        var foo = 10;  
    }  
    alert(foo);  
}  
bar();  

结果是10;
再看下面这个

var a = 1;  
function b() {  
    a = 10;  
    return;  
    function a() {}  
}  
b();  
alert(a); 

结果是1

出乎意料的结果是由于“Hoisting (变量提升)”的原因,要理解其中的原理需要先了解下JavaScript的作用域scope。

javascript作用域(函数作用域)与C语言作用域(块级作用域)不同

int main() {  
    int x = 1;  
    printf("%d, ", x); // 1  
    if (1) {  
        int x = 2;  
        printf("%d, ", x); // 2  
    }  
    printf("%d\n", x); // 1  
}  

这是因为C家族的语言有块作用域,当程序控制走进一个块,比如if块,只作用于该块的变量可以被声明,而不会影响块外面的作用域。但是在Javascript里面,这样不行

var x = 1;  
console.log(x); // 1  
if (true) {  
    var x = 2;  
    console.log(x); // 2  
}  
console.log(x); // 2  

函数声明和变量声明总是会被解释器悄悄地被“提升”到方法体的最顶部。这个意思是,像下面的代码:

function foo() {  
    bar();  
    var x = 1;  
} 

实际上会被解释成:

function foo() {  
    var x;  
    bar();  
    x = 1;  
}  

无论定义该变量的块是否能被执行。下面的两个函数实际上是一回事:

function foo() {  
    if (false) {  
        var x = 1;  
    }  
    return;  
    var y = 1;  
}  
function foo() {  
    var x, y;  
    if (false) {  
        x = 1;  
    }  
    return;  
    y = 1;  
}  

只有函数式的声明才会连同函数体一起被提升。foo的声明会被提升,但是它指向的函数体只会在执行的时候才被赋值

function test() {  
    foo(); // TypeError "foo is not a function"  
    bar(); // "this will run!"  
    var foo = function () { // 变量指向函数表达式  
        alert("this won't run!");  
    }  
    function bar() { // 函数声明 函数名为bar  
        alert("this will run!");  
    }  
}  
test(); 

如果程序员不能很好的理解变量提升,他们写的程序就容易出现一些问题。
为了避免这些问题,通常我们在每个作用域开始前声明这些变量,这也是正常的 JavaScript 解析步骤,易于我们理解。

JavaScript 严格模式(strict mode)不允许使用未声明的变量。

原文链接猛戳这里

JavaScript Object-Oriented

JavaScript构造函数

function Person (name,age) {
    this.name = name;
    this.age = age;
    this.type = "human";
    this.play = function(){console.log("video game")};
}

//下面生成实例
var Person1 = new Person("Tom",25);
var Person2 = new Person("Jack",26);
alert(Person1.name);

//这时Person1和Person2会自动含有一个constructor属性,指向它们的构造函数。
alert(Person1.constructor);
//Javascript还提供了一个instanceof运算符,验证原型对象与实例对象之间的关系
alert(Person1 instanceof Person); //true

alert(Person1.type == Person2.type);//ture
alert(Person1.play == Person2.play);//false

type属性和play()方法都是一模一样的内容,每一次生成一个实例,都必须为重复的内容,多占用一些内存.

Prototype模式

Javascript规定,每一个构造函数都有一个prototype属性,指向另一个对象。这个对象的所有属性和方法,都会被构造函数的实例继承。
这意味着,我们可以把那些不变的属性和方法,直接定义在prototype对象上.

function Person (name,age) {
    this.name = name;
    this.age = age;
}
Person.prototype.type = "human";
Person.prototype.play = function(){console.log("video game")};

var Person1 = new Person("Tom",25);
var Person2 = new Person("Jack",26);
alert(Person1.type); //human
alert(Person1.play == Person2.play); //true

这时所有实例的type属性和play()方法,其实都是同一个内存地址,指向prototype对象,使用原型的好处是可以让对象实例共享它所包含的属性和方法,因此就提高了运行效率。

在JavaScript中,一共有两种类型的值,原始值和对象值。每个对象都有一个内部属性 prototype ,我们通常称之为原型。原型的值可以是一个对象,也可以是null。如果它的值是一个对象,则这个对象也一定有自己的原型。这样就形成了一条线性的链,我们称之为原型链。
关于原型、原型链-猛戳

ECMAScript数据类型

原始类型

ECMAScript 有 5 种原始类型(primitive type),即 Undefined、Null、Boolean、Number 和 String。
原始数据类型

引用类型

引用类型通常叫做类(class),也就是说,遇到引用值,所处理的就是对象。

Object 对象
Object 对象自身用处不大,不过在了解其他类之前,还是应该了解它。因为 ECMAScript 中的 Object 对象与 Java 中的 java.lang.Object 相似,ECMAScript 中的所有对象都由这个对象继承而来,Object 对象中的所有属性和方法都会出现在其他对象中,所以理解了 Object 对象,就可以更好地理解其他对象。

Object 对象具有下列属性
constructor
对创建对象的函数的引用(指针)。对于 Object 对象,该指针指向原始的 Object() 函数。
Prototype
对该对象的对象原型的引用。对于所有的对象,它默认返回 Object 对象的一个实例。

类型转换

所有程序设计语言最重要的特征之一是具有进行类型转换的能力。
ECMAScript 给开发者提供了大量简单的类型转换方法。

  • toString()
  • parseInt()
  • parseFloat()

来了老弟
508 声望31 粉丝

纸上得来终觉浅,绝知此事要躬行